package com.changebitmapcolor;

import java.io.InputStream;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Shader.TileMode;
import android.graphics.drawable.Drawable;

/**
 * ???????????????
 *
 */
public class BitmapUtils {
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @param newWidth ????????????
	 * @param newHeight ????????????
	 * @return ??????????????????
	 */
	public static Bitmap scale(Bitmap bitmap, int newWidth, int newHeight) {
		//??????????????????
		int width = bitmap.getWidth();
		//??????????????????
		int height = bitmap.getHeight();
		//???????????????????????????????????????
		Matrix matrix = new Matrix();
		//???????????????????????????
		matrix.postScale(((float) newWidth / width), ((float) newHeight / height));
		//????????????????????????????????????????????????
		return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
	}
	
	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ????????????????????????
	 */
	public static Bitmap reverseByHorizontal(Bitmap bitmap){
		//??????????????????
		Matrix matrix = new Matrix();
		//????????????
		matrix.preScale(-1, 1);
		//??????????????????????????????????????????
		return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
	}
	
	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ????????????????????????
	 */
	public static Bitmap reverseByVertical(Bitmap bitmap){
		//??????????????????
		Matrix matrix = new Matrix();
		//????????????
		matrix.preScale(1, -1);
		//??????????????????????????????????????????
		return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
	}
	
	/**
	 * ???????????????ID???Drawable?????????Bitmap
	 * @param context ?????????
	 * @param resId Drawable???????????????ID
	 * @return ??????Bitmap
	 */
	public static Bitmap drawableToBitmapByResouceId(Context context, int resId) {
		BitmapFactory.Options opt = new BitmapFactory.Options();
		opt.inPreferredConfig = Bitmap.Config.RGB_565;
		opt.inPurgeable = true;
		opt.inInputShareable = true;
		InputStream is = context.getResources().openRawResource(resId);
		return BitmapFactory.decodeStream(is, null, opt);
	}
	
	/**
	 * ????????????
	 * @param bitmap ?????????
	 * @param pixels ????????????????????????????????????
	 * @return ???????????????????????????
	 */
	public static Bitmap roundCorner(Bitmap bitmap, float pixels) { 
		//???????????????????????????????????????????????????
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Config.ARGB_8888); 
        //?????????????????????????????????????????????
        Canvas canvas = new Canvas(output); 
        //????????????
        final Paint paint = new Paint(); 
        //????????????????????????????????????????????????????????????????????????????????????
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight()); 
        //????????????????????????????????????????????????????????????
        final RectF rectF = new RectF(rect); 
        paint.setAntiAlias(true); 
        //??????????????????????????????
        canvas.drawARGB(0, 0, 0, 0); 
        //??????????????????????????????????????????
        paint.setColor(0xff424242); 
        //??????????????????????????????????????????????????????????????????????????????
        canvas.drawRoundRect(rectF, pixels, pixels, paint); 
        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN)); 
        //?????????paint?????????bitmap??????????????????????????????
        canvas.drawBitmap(bitmap, rect, rect, paint); 
        return output; 
    }
	
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @param reflectionSpacing ??????????????????????????????
	 * @return ????????????????????????
	 */
	public static Bitmap reflection(Bitmap bitmap, int reflectionSpacing, int reflectionHeight) {
		//???????????????
		int width = bitmap.getWidth();
		//???????????????
		int height = bitmap.getHeight();

		//??????????????????
		Bitmap reflectionImage = reverseByVertical(bitmap);
		
		//???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
		Bitmap bitmapWithReflection = Bitmap.createBitmap(width, height + reflectionSpacing + reflectionHeight, Config.ARGB_8888);
		Canvas canvas = new Canvas(bitmapWithReflection);
		/*
		 * ?????????????????????????????????
		 */
		//????????????????????????????????????
		canvas.drawBitmap(bitmap, 0, 0, null);
		//???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
		canvas.drawBitmap(reflectionImage, 0, height + reflectionSpacing, null);
		/*
		 * ????????????????????????
		 */
		//???????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
		Paint paint = new Paint();
		paint.setShader(new LinearGradient(0, bitmap.getHeight(), 0, bitmapWithReflection.getHeight() + reflectionSpacing, 0x70ffffff, 0x00ffffff, TileMode.CLAMP));
		paint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
		canvas.drawRect(0, height+reflectionSpacing, width, bitmapWithReflection.getHeight() + reflectionSpacing, paint);
		return bitmapWithReflection;
	}
	
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @return ????????????????????????
	 */
	public static Bitmap reflection(Bitmap bitmap) {
		return reflection(bitmap, 4, bitmap.getHeight()/2);
	}
	
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @param angle ????????????
	 * @param px ??????????????????X????????????
	 * @param py ??????????????????Y????????????
	 * @return ??????????????????
	 */
	public static Bitmap rotate(Bitmap bitmap, float angle, float px, float py){
		Matrix matrix = new Matrix();
		matrix.postRotate(angle, px, py);
		return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
	}
	
	/**
	 * ???????????????
	 * @param bitmap ??????
	 * @param angle ????????????
	 * @return ??????????????????
	 */
	public static Bitmap rotate(Bitmap bitmap, float angle){
		Matrix matrix = new Matrix();
		matrix.postRotate(angle);
		return Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, false);
	}
	
	/**
	 * ???????????????
	 * @param bitmap ??????
	 * @param saturationValue ??????????????????
	 * @return ????????????????????????????????????
	 */
	public static Bitmap saturation(Bitmap bitmap, int saturationValue){
		//????????????????????????????????????
		float newSaturationValue = saturationValue * 1.0F / 127;
		//????????????????????????
		ColorMatrix saturationColorMatrix = new ColorMatrix();
		//??????????????????
		saturationColorMatrix.setSaturation(newSaturationValue);
		//?????????????????????????????????????????????
		Paint paint = new Paint();
		paint.setColorFilter(new ColorMatrixColorFilter(saturationColorMatrix));
		//???????????????????????????????????????
		Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(newBitmap);
		//?????????????????????????????????????????????
		canvas.drawBitmap(bitmap, 0, 0, paint);
		return newBitmap;
	}
	
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @param lumValue ???????????????
	 * @return ?????????????????????????????????
	 */
	public static Bitmap lum(Bitmap bitmap, int lumValue){
		//?????????????????????????????????
		float newlumValue = lumValue * 1.0F / 127;
		//????????????????????????
		ColorMatrix lumColorMatrix = new ColorMatrix();
		//???????????????
		lumColorMatrix.setScale(newlumValue, newlumValue, newlumValue, 1);
		//?????????????????????????????????????????????
		Paint paint = new Paint();
		paint.setColorFilter(new ColorMatrixColorFilter(lumColorMatrix));
		//???????????????????????????????????????
		Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(newBitmap);
		//?????????????????????????????????????????????
		canvas.drawBitmap(bitmap, 0, 0, paint);
		return newBitmap;
	}
	
	/**
	 * ????????????
	 * @param bitmap ??????
	 * @param hueValue ???????????????
	 * @return ?????????????????????????????????
	 */
	public static Bitmap hue(Bitmap bitmap, int hueValue){
		//?????????????????????????????????
		float newHueValue = (hueValue - 127) * 1.0F / 127 * 180;
		//????????????????????????
		ColorMatrix hueColorMatrix = new ColorMatrix();
		// ?????????????????????????????????????????????
		hueColorMatrix.setRotate(0, newHueValue);   
		// ????????????????????????????????????????????????  
		hueColorMatrix.setRotate(1, newHueValue); 
		// ?????????????????????????????????????????????
		hueColorMatrix.setRotate(2, newHueValue); 
		//?????????????????????????????????????????????
		Paint paint = new Paint();
		paint.setColorFilter(new ColorMatrixColorFilter(hueColorMatrix));
		//???????????????????????????????????????
		Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(newBitmap);
		//?????????????????????????????????????????????
		canvas.drawBitmap(bitmap, 0, 0, paint);
		return newBitmap;
	}
	
	/**
	 * ?????????????????????????????????
	 * @param bitmap ??????
	 * @param lumValue ?????????
	 * @param hueValue ?????????
	 * @param saturationValue ????????????
	 * @return ?????????????????????????????????????????????
	 */
	public static Bitmap lumAndHueAndSaturation(Bitmap bitmap, int lumValue, int hueValue, int saturationValue){
		//????????????????????????????????????
		float newSaturationValue = saturationValue * 1.0F / 127;
		//?????????????????????????????????
		float newlumValue = lumValue * 1.0F / 127;
		//?????????????????????????????????
		float newHueValue = (hueValue - 127) * 1.0F / 127 * 180;
		
		//?????????????????????????????????????????????
		ColorMatrix colorMatrix = new ColorMatrix();
		
		//??????????????????
		colorMatrix.setSaturation(newSaturationValue);
		//???????????????
		colorMatrix.setScale(newlumValue, newlumValue, newlumValue, 1);
		// ?????????????????????????????????????????????
		colorMatrix.setRotate(0, newHueValue);   
		// ????????????????????????????????????????????????  
		colorMatrix.setRotate(1, newHueValue); 
		// ?????????????????????????????????????????????
		colorMatrix.setRotate(2, newHueValue); 
		
		//?????????????????????????????????????????????
		Paint paint = new Paint();
		paint.setColorFilter(new ColorMatrixColorFilter(colorMatrix));
		//???????????????????????????????????????
		Bitmap newBitmap = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas canvas = new Canvas(newBitmap);
		//?????????????????????????????????????????????
		canvas.drawBitmap(bitmap, 0, 0, paint);
		return newBitmap;
	}
	
	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap nostalgic(Bitmap bitmap) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
		int pixColor = 0;
		int pixR = 0;
		int pixG = 0;
		int pixB = 0;
		int newR = 0;
		int newG = 0;
		int newB = 0;
		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		for (int i = 0; i < height; i++) {
			for (int k = 0; k < width; k++) {
				pixColor = pixels[width * i + k];
				pixR = Color.red(pixColor);
				pixG = Color.green(pixColor);
				pixB = Color.blue(pixColor);
				newR = (int) (0.393 * pixR + 0.769 * pixG + 0.189 * pixB);
				newG = (int) (0.349 * pixR + 0.686 * pixG + 0.168 * pixB);
				newB = (int) (0.272 * pixR + 0.534 * pixG + 0.131 * pixB);
				int newColor = Color.argb(255, newR > 255 ? 255 : newR, newG > 255 ? 255 : newG, newB > 255 ? 255
						: newB);
				pixels[width * i + k] = newColor;
			}
		}
		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}
	
	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap blur(Bitmap bitmap) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;

		int newColor = 0;

		int[][] colors = new int[9][3];
		for (int i = 1, length = width - 1; i < length; i++) {
			for (int k = 1, len = height - 1; k < len; k++) {
				for (int m = 0; m < 9; m++) {
					int s = 0;
					int p = 0;
					switch (m) {
					case 0:
						s = i - 1;
						p = k - 1;
						break;
					case 1:
						s = i;
						p = k - 1;
						break;
					case 2:
						s = i + 1;
						p = k - 1;
						break;
					case 3:
						s = i + 1;
						p = k;
						break;
					case 4:
						s = i + 1;
						p = k + 1;
						break;
					case 5:
						s = i;
						p = k + 1;
						break;
					case 6:
						s = i - 1;
						p = k + 1;
						break;
					case 7:
						s = i - 1;
						p = k;
						break;
					case 8:
						s = i;
						p = k;
					}
					pixColor = bitmap.getPixel(s, p);
					colors[m][0] = Color.red(pixColor);
					colors[m][1] = Color.green(pixColor);
					colors[m][2] = Color.blue(pixColor);
				}

				for (int m = 0; m < 9; m++) {
					newR += colors[m][0];
					newG += colors[m][1];
					newB += colors[m][2];
				}

				newR = (int) (newR / 9F);
				newG = (int) (newG / 9F);
				newB = (int) (newB / 9F);

				newR = Math.min(255, Math.max(0, newR));
				newG = Math.min(255, Math.max(0, newG));
				newB = Math.min(255, Math.max(0, newB));

				newColor = Color.argb(255, newR, newG, newB);
				newBitmap.setPixel(i, k, newColor);

				newR = 0;
				newG = 0;
				newB = 0;
			}
		}
		return newBitmap;
	}

	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap soften(Bitmap bitmap) {
		// ????????????
		int[] gauss = new int[] { 1, 2, 1, 2, 4, 2, 1, 2, 1 };

		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixR = 0;
		int pixG = 0;
		int pixB = 0;

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;

		int delta = 16; // ??????????????????????????????????????????

		int idx = 0;
		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		for (int i = 1, length = height - 1; i < length; i++) {
			for (int k = 1, len = width - 1; k < len; k++) {
				idx = 0;
				for (int m = -1; m <= 1; m++) {
					for (int n = -1; n <= 1; n++) {
						pixColor = pixels[(i + m) * width + k + n];
						pixR = Color.red(pixColor);
						pixG = Color.green(pixColor);
						pixB = Color.blue(pixColor);

						newR = newR + (int) (pixR * gauss[idx]);
						newG = newG + (int) (pixG * gauss[idx]);
						newB = newB + (int) (pixB * gauss[idx]);
						idx++;
					}
				}

				newR /= delta;
				newG /= delta;
				newB /= delta;

				newR = Math.min(255, Math.max(0, newR));
				newG = Math.min(255, Math.max(0, newG));
				newB = Math.min(255, Math.max(0, newB));

				pixels[i * width + k] = Color.argb(255, newR, newG, newB);

				newR = 0;
				newG = 0;
				newB = 0;
			}
		}

		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}

	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @param centerX ?????????X????????????
	 * @param centerY ?????????Y????????????
	 * @return ??????????????????????????????
	 */
	public static Bitmap sunshine(Bitmap bitmap, int centerX, int centerY) {
		final int width = bitmap.getWidth();
		final int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixR = 0;
		int pixG = 0;
		int pixB = 0;

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;
		int radius = Math.min(centerX, centerY);

		final float strength = 150F; // ???????????? 100~150
		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		int pos = 0;
		for (int i = 1, length = height - 1; i < length; i++) {
			for (int k = 1, len = width - 1; k < len; k++) {
				pos = i * width + k;
				pixColor = pixels[pos];

				pixR = Color.red(pixColor);
				pixG = Color.green(pixColor);
				pixB = Color.blue(pixColor);

				newR = pixR;
				newG = pixG;
				newB = pixB;

				// ????????????????????????????????????????????????????????????????????????????????????
				int distance = (int) (Math.pow((centerY - i), 2) + Math.pow(centerX - k, 2));
				if (distance < radius * radius) {
					// ??????????????????????????????????????????
					int result = (int) (strength * (1.0 - Math.sqrt(distance) / radius));
					newR = pixR + result;
					newG = pixG + result;
					newB = pixB + result;
				}

				newR = Math.min(255, Math.max(0, newR));
				newG = Math.min(255, Math.max(0, newG));
				newB = Math.min(255, Math.max(0, newB));

				pixels[pos] = Color.argb(255, newR, newG, newB);
			}
		}

		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}

	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap film(Bitmap bitmap) {
		// RGBA????????????
		final int MAX_VALUE = 255;
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixR = 0;
		int pixG = 0;
		int pixB = 0;

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;

		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		int pos = 0;
		for (int i = 1, length = height - 1; i < length; i++) {
			for (int k = 1, len = width - 1; k < len; k++) {
				pos = i * width + k;
				pixColor = pixels[pos];

				pixR = Color.red(pixColor);
				pixG = Color.green(pixColor);
				pixB = Color.blue(pixColor);

				newR = MAX_VALUE - pixR;
				newG = MAX_VALUE - pixG;
				newB = MAX_VALUE - pixB;

				newR = Math.min(MAX_VALUE, Math.max(0, newR));
				newG = Math.min(MAX_VALUE, Math.max(0, newG));
				newB = Math.min(MAX_VALUE, Math.max(0, newB));

				pixels[pos] = Color.argb(MAX_VALUE, newR, newG, newB);
			}
		}

		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}

	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap sharpen(Bitmap bitmap) {
		// ??????????????????
		int[] laplacian = new int[] { -1, -1, -1, -1, 9, -1, -1, -1, -1 };

		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixR = 0;
		int pixG = 0;
		int pixB = 0;

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;

		int idx = 0;
		float alpha = 0.3F;
		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		for (int i = 1, length = height - 1; i < length; i++) {
			for (int k = 1, len = width - 1; k < len; k++) {
				idx = 0;
				for (int m = -1; m <= 1; m++) {
					for (int n = -1; n <= 1; n++) {
						pixColor = pixels[(i + n) * width + k + m];
						pixR = Color.red(pixColor);
						pixG = Color.green(pixColor);
						pixB = Color.blue(pixColor);

						newR = newR + (int) (pixR * laplacian[idx] * alpha);
						newG = newG + (int) (pixG * laplacian[idx] * alpha);
						newB = newB + (int) (pixB * laplacian[idx] * alpha);
						idx++;
					}
				}

				newR = Math.min(255, Math.max(0, newR));
				newG = Math.min(255, Math.max(0, newG));
				newB = Math.min(255, Math.max(0, newB));

				pixels[i * width + k] = Color.argb(255, newR, newG, newB);
				newR = 0;
				newG = 0;
				newB = 0;
			}
		}

		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}

	/**
	 * ??????????????????
	 * @param bitmap ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap emboss(Bitmap bitmap) {
		int width = bitmap.getWidth();
		int height = bitmap.getHeight();
		Bitmap newBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);

		int pixR = 0;
		int pixG = 0;
		int pixB = 0;

		int pixColor = 0;

		int newR = 0;
		int newG = 0;
		int newB = 0;

		int[] pixels = new int[width * height];
		bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
		int pos = 0;
		for (int i = 1, length = height - 1; i < length; i++) {
			for (int k = 1, len = width - 1; k < len; k++) {
				pos = i * width + k;
				pixColor = pixels[pos];

				pixR = Color.red(pixColor);
				pixG = Color.green(pixColor);
				pixB = Color.blue(pixColor);

				pixColor = pixels[pos + 1];
				newR = Color.red(pixColor) - pixR + 127;
				newG = Color.green(pixColor) - pixG + 127;
				newB = Color.blue(pixColor) - pixB + 127;

				newR = Math.min(255, Math.max(0, newR));
				newG = Math.min(255, Math.max(0, newG));
				newB = Math.min(255, Math.max(0, newB));

				pixels[pos] = Color.argb(255, newR, newG, newB);
			}
		}

		newBitmap.setPixels(pixels, 0, width, 0, 0, width, height);
		return newBitmap;
	}
	
	/**
	 * ??????????????????
	 * @param bmp ??????
	 * @return ??????????????????????????????
	 */
	public static Bitmap sketch(Bitmap bmp) {
//		int pos, row, col, clr;
//		int width = bmp.getWidth();
//		int height = bmp.getHeight();
//		int[] pixSrc = new int[width * height];
//		int[] pixNvt = new int[width * height];
//		// ??????????????????????????????????????????????????????
//		bmp.getPixels(pixSrc, 0, width, 0, 0, width, height);
//		
//		for (row = 0; row < height; row++) {
//			for (col = 0; col < width; col++) {
//				pos = row * width + col;
//				pixSrc[pos] = (Color.red(pixSrc[pos]) + Color.green(pixSrc[pos]) + Color.blue(pixSrc[pos])) / 3;
//				pixNvt[pos] = 255 - pixSrc[pos];
//			}
//		}
//
//		// ????????????????????????????????????, ??????????????????????????????5.0
//		gaussGray(pixNvt, 5.0, 5.0, width, height);
//
//		// ????????????????????????????????????????????????
//		for (row = 0; row < height; row++) {
//			for (col = 0; col < width; col++) {
//				pos = row * width + col;
//
//				clr = pixSrc[pos] << 8;
//				clr /= 256 - pixNvt[pos];
//				clr = Math.min(clr, 255);
//
//				pixSrc[pos] = Color.rgb(clr, clr, clr);
//			}
//		}
//		bmp.setPixels(pixSrc, 0, width, 0, 0, width, height);
//		return bmp;
		return null;
	}
	
//	private static int gaussGray(int[] psrc, double horz, double vert, int width, int height) {
//		int[] dst, src;
//		double[] n_p, n_m, d_p, d_m, bd_p, bd_m;
//		double[] val_p, val_m;
//		int i, j, t, k, row, col, terms;
//		int[] initial_p, initial_m;
//		double std_dev;
//		int row_stride = width;
//		int max_len = Math.max(width, height);
//		int sp_p_idx, sp_m_idx, vp_idx, vm_idx;
//
//		val_p = new double[max_len];
//		val_m = new double[max_len];
//
//		n_p = new double[5];
//		n_m = new double[5];
//		d_p = new double[5];
//		d_m = new double[5];
//		bd_p = new double[5];
//		bd_m = new double[5];
//
//		src = new int[max_len];
//		dst = new int[max_len];
//
//		initial_p = new int[4];
//		initial_m = new int[4];
//
//		// ????????????
//		if (vert > 0.0) {
//			vert = Math.abs(vert) + 1.0;
//			std_dev = Math.sqrt(-(vert * vert) / (2 * Math.log(1.0 / 255.0)));
//
//			// ???????????????
//			findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
//
//			for (col = 0; col < width; col++) {
//				for (k = 0; k < max_len; k++) {
//					val_m[k] = val_p[k] = 0;
//				}
//
//				for (t = 0; t < height; t++) {
//					src[t] = psrc[t * row_stride + col];
//				}
//
//				sp_p_idx = 0;
//				sp_m_idx = height - 1;
//				vp_idx = 0;
//				vm_idx = height - 1;
//
//				initial_p[0] = src[0];
//				initial_m[0] = src[height - 1];
//
//				for (row = 0; row < height; row++) {
//					terms = (row < 4) ? row : 4;
//
//					for (i = 0; i <= terms; i++) {
//						val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i] * val_p[vp_idx - i];
//						val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i] * val_m[vm_idx + i];
//					}
//					for (j = i; j <= 4; j++) {
//						val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
//						val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
//					}
//
//					sp_p_idx++;
//					sp_m_idx--;
//					vp_idx++;
//					vm_idx--;
//				}
//
//				transferGaussPixels(val_p, val_m, dst, 1, height);
//
//				for (t = 0; t < height; t++) {
//					psrc[t * row_stride + col] = dst[t];
//				}
//			}
//		}
//
//		// ????????????
//		if (horz > 0.0) {
//			horz = Math.abs(horz) + 1.0;
//
//			if (horz != vert) {
//				std_dev = Math.sqrt(-(horz * horz) / (2 * Math.log(1.0 / 255.0)));
//
//				// ???????????????
//				findConstants(n_p, n_m, d_p, d_m, bd_p, bd_m, std_dev);
//			}
//
//			for (row = 0; row < height; row++) {
//				for (k = 0; k < max_len; k++) {
//					val_m[k] = val_p[k] = 0;
//				}
//
//				for (t = 0; t < width; t++) {
//					src[t] = psrc[row * row_stride + t];
//				}
//
//				sp_p_idx = 0;
//				sp_m_idx = width - 1;
//				vp_idx = 0;
//				vm_idx = width - 1;
//
//				initial_p[0] = src[0];
//				initial_m[0] = src[width - 1];
//
//				for (col = 0; col < width; col++) {
//					terms = (col < 4) ? col : 4;
//
//					for (i = 0; i <= terms; i++) {
//						val_p[vp_idx] += n_p[i] * src[sp_p_idx - i] - d_p[i] * val_p[vp_idx - i];
//						val_m[vm_idx] += n_m[i] * src[sp_m_idx + i] - d_m[i] * val_m[vm_idx + i];
//					}
//					for (j = i; j <= 4; j++) {
//						val_p[vp_idx] += (n_p[j] - bd_p[j]) * initial_p[0];
//						val_m[vm_idx] += (n_m[j] - bd_m[j]) * initial_m[0];
//					}
//
//					sp_p_idx++;
//					sp_m_idx--;
//					vp_idx++;
//					vm_idx--;
//				}
//
//				transferGaussPixels(val_p, val_m, dst, 1, width);
//
//				for (t = 0; t < width; t++) {
//					psrc[row * row_stride + t] = dst[t];
//				}
//			}
//		}
//
//		return 0;
//	}
	
//	private static void findConstants(double[] n_p, double[] n_m, double[] d_p, double[] d_m, double[] bd_p,
//			double[] bd_m, double std_dev) {
//		double div = Math.sqrt(2 * 3.141593) * std_dev;
//		double x0 = -1.783 / std_dev;
//		double x1 = -1.723 / std_dev;
//		double x2 = 0.6318 / std_dev;
//		double x3 = 1.997 / std_dev;
//		double x4 = 1.6803 / div;
//		double x5 = 3.735 / div;
//		double x6 = -0.6803 / div;
//		double x7 = -0.2598 / div;
//		int i;
//
//		n_p[0] = x4 + x6;
//		n_p[1] = (Math.exp(x1) * (x7 * Math.sin(x3) - (x6 + 2 * x4) * Math.cos(x3)) + Math.exp(x0)
//				* (x5 * Math.sin(x2) - (2 * x6 + x4) * Math.cos(x2)));
//		n_p[2] = (2
//				* Math.exp(x0 + x1)
//				* ((x4 + x6) * Math.cos(x3) * Math.cos(x2) - x5 * Math.cos(x3) * Math.sin(x2) - x7 * Math.cos(x2)
//						* Math.sin(x3)) + x6 * Math.exp(2 * x0) + x4 * Math.exp(2 * x1));
//		n_p[3] = (Math.exp(x1 + 2 * x0) * (x7 * Math.sin(x3) - x6 * Math.cos(x3)) + Math.exp(x0 + 2 * x1)
//				* (x5 * Math.sin(x2) - x4 * Math.cos(x2)));
//		n_p[4] = 0.0;
//
//		d_p[0] = 0.0;
//		d_p[1] = -2 * Math.exp(x1) * Math.cos(x3) - 2 * Math.exp(x0) * Math.cos(x2);
//		d_p[2] = 4 * Math.cos(x3) * Math.cos(x2) * Math.exp(x0 + x1) + Math.exp(2 * x1) + Math.exp(2 * x0);
//		d_p[3] = -2 * Math.cos(x2) * Math.exp(x0 + 2 * x1) - 2 * Math.cos(x3) * Math.exp(x1 + 2 * x0);
//		d_p[4] = Math.exp(2 * x0 + 2 * x1);
//
//		for (i = 0; i <= 4; i++) {
//			d_m[i] = d_p[i];
//		}
//
//		n_m[0] = 0.0;
//		for (i = 1; i <= 4; i++) {
//			n_m[i] = n_p[i] - d_p[i] * n_p[0];
//		}
//
//		double sum_n_p, sum_n_m, sum_d;
//		double a, b;
//
//		sum_n_p = 0.0;
//		sum_n_m = 0.0;
//		sum_d = 0.0;
//
//		for (i = 0; i <= 4; i++) {
//			sum_n_p += n_p[i];
//			sum_n_m += n_m[i];
//			sum_d += d_p[i];
//		}
//
//		a = sum_n_p / (1.0 + sum_d);
//		b = sum_n_m / (1.0 + sum_d);
//
//		for (i = 0; i <= 4; i++) {
//			bd_p[i] = d_p[i] * a;
//			bd_m[i] = d_m[i] * b;
//		}
//	}

//	private static void transferGaussPixels(double[] src1, double[] src2, int[] dest, int bytes, int width) {
//		int i, j, k, b;
//		int bend = bytes * width;
//		double sum;
//
//		i = j = k = 0;
//		for (b = 0; b < bend; b++) {
//			sum = src1[i++] + src2[j++];
//
//			if (sum > 255)
//				sum = 255;
//			else if (sum < 0)
//				sum = 0;
//
//			dest[k++] = (int) sum;
//		}
//	}

	/**
	 * ???YUV?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
	 * @param sourceData YUV???????????????????????????
	 * @param width ???????????????
	 * @param height ???????????????
	 * @return 
	 */
	public static final byte[] yuvLandscapeToPortrait(byte[] sourceData, int width, int height){
		byte[] rotatedData = new byte[sourceData.length];
		for (int y = 0; y < height; y++) {
			for (int x = 0; x < width; x++)
				rotatedData[x * height + height - y - 1] = sourceData[x + y * width];
		}
		return rotatedData;
	}
	
	/**
	 * ???????????????
	 * @param imageFilePath ????????????
	 * @param thumbnailWidth ??????????????????
	 * @param thumbnailHeight ??????????????????
	 * @return
	 */
	public Bitmap getThumbnail(String imageFilePath, int thumbnailWidth, int thumbnailHeight) {
		/* ????????????????????????????????? */
		BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;//???????????????true??????????????????????????????????????????????????????????????????????????????????????????Options???
		BitmapFactory.decodeFile(imageFilePath,options);//?????????????????????options???inJustDecodeBounds???????????????true?????????????????????null
		int sourceImageWidth = options.outWidth;//????????????????????????
		int sourceImageHeight = options.outHeight;//????????????????????????
		
		/* ?????????????????????????????????????????????????????????????????????????????????????????????????????? */
		int scaling = 1;//1??????????????????
		if (sourceImageWidth > sourceImageHeight && sourceImageWidth > thumbnailWidth) {//???????????????????????????????????????????????????
			scaling = (int) (options.outWidth / thumbnailWidth);
		} else if (sourceImageWidth < sourceImageHeight && sourceImageHeight > thumbnailHeight) {//???????????????????????????????????????????????????
			scaling = (int) (options.outHeight / thumbnailHeight);
		}
		if (scaling <= 0){
			scaling = 1;
		}
		options.inSampleSize = scaling;//??????????????????
		
		/* ????????????????????????????????????????????????????????????????????????options???inJustDecodeBounds?????????false??? */
		options.inJustDecodeBounds = false;//?????????false
		return BitmapFactory.decodeFile(imageFilePath, options);
	}
	
	/**
	 * Drawable?????????Bitmap
	 * @param drawable
	 * @return
	 */
	public static Bitmap drawableToBitmap(Drawable drawable) {       
		if(drawable != null){
			Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight(), drawable.getOpacity() != PixelFormat.OPAQUE  ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565);
			Canvas canvas = new Canvas(bitmap);
			drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
			drawable.draw(canvas);
			return bitmap;
		}else{
			return null;
		}
	}
	
	/**
	 * ??????BitmapFactory.Options?????????????????????
	 * @param options
	 * @param minSideLength ???????????????????????????????????????
	 * @param maxNumOfPixels ??????????????????????????????????????????
	 * @return
	 */
	public static int computeSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
	    int initialSize = computeInitialSampleSize(options, minSideLength, maxNumOfPixels);
	    int roundedSize;
	    if (initialSize <= 8) {
	        roundedSize = 1;
	        while (roundedSize < initialSize) {
	            roundedSize <<= 1;
	        }
	    } else {
	        roundedSize = (initialSize + 7) / 8 * 8;
	    }
	    return roundedSize;
	}
	
	private static int computeInitialSampleSize(BitmapFactory.Options options, int minSideLength, int maxNumOfPixels) {
	    double w = options.outWidth;
	    double h = options.outHeight;
	    int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math.sqrt(w * h / maxNumOfPixels));
	    int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math.floor(w / minSideLength), Math.floor(h / minSideLength));
	    if (upperBound < lowerBound) {
	        return lowerBound;
	    }

	    if ((maxNumOfPixels == -1) &&
	            (minSideLength == -1)) {
	        return 1;
	    } else if (minSideLength == -1) {
	        return lowerBound;
	    } else {
	        return upperBound;
	    }
	}
}

